var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var Pjs2;
(function (Pjs2) {
    var Pjs2Console = (function (_super) {
        __extends(Pjs2Console, _super);
        function Pjs2Console(container) {
            var _this = this;
            _super.call(this, container);
            this.parser = new Pjs2.Parser();
            this.history = new Array();
            this.historyPos = 0;
            this.multiLine = false;
            this.script = "";
            this.runtime = new Pjs2.Runtime();
            this.showParsedScript = true;
            this.running = true;
            this.actualTableHead = null;
            this.catchErrors = true;

            this.runtime.AddFunction(new Pjs2.FunctionDefinition(function (r, p) {
                _this.showParsedScript = p["Value"];
            }, [
                new Pjs2.FuncParameterDefinition("Value", true, true, function (o) {
                    return typeof o == "boolean";
                })
            ], "Set-ShowParsedScript"));
            this.runtime.AddAlias("showparsed", "Set-ShowParsedScript");

            this.runtime.AddFunction(new Pjs2.FunctionDefinition(function (r, p) {
                _this.WriteLine(p["object"].toString());
                _this.WriteLine("");
            }, [
                new Pjs2.FuncParameterDefinition("Object", true, true)
            ], "Write-Host"));

            this.runtime.AddFunction(new Pjs2.FunctionDefinition(function (r, p) {
                var obj = p["inputobject"];
                if (!(obj instanceof Array))
                    obj = [obj];

                if (p["expand"])
                    obj = obj.map(function (o) {
                        return o[p["expand"]];
                    });

                var par = new Array();
                if (p["property"]) {
                    var prop = p["property"];
                    if (!(prop instanceof Array))
                        prop = [prop];
                    par = prop;
                } else {
                    var f = FormatingRules.FromObjTable(obj);
                    for (var p in f) {
                        par.push(p);
                    }
                }

                _this.WriteTable(obj, p);
            }, [
                new Pjs2.FuncParameterDefinition("Property", false, false),
                new Pjs2.FuncParameterDefinition("InputObject", true, true),
                new Pjs2.FuncParameterDefinition("AutoSize", false, false, function (o) {
                    return typeof o == "boolean";
                }),
                new Pjs2.FuncParameterDefinition("Expand", false, false, function (o) {
                    return typeof o == "string";
                })
            ], "Format-Table"));

            this.runtime.AddFunction(new Pjs2.FunctionDefinition(function (r, p) {
                var obj = p["inputobject"];
                if (!(obj instanceof Array))
                    obj = [obj];
                if (p["expand"])
                    obj = obj.map(function (o) {
                        return o[p["expand"]];
                    });
                obj.forEach(function (o) {
                    return _this.WriteJson(o, null, p["spacing"]);
                });
            }, [
                new Pjs2.FuncParameterDefinition("InputObject", true, true),
                new Pjs2.FuncParameterDefinition("Expand", false, false, function (o) {
                    return typeof o == "string";
                }),
                new Pjs2.FuncParameterDefinition("Spacing", false, false, function (o) {
                    return typeof o == "string";
                })
            ], "Format-Json"));
            this.runtime.AddAlias("fj", "Format-Json");

            this.runtime.AddFunction(new Pjs2.FunctionDefinition(function (r, p) {
                if (p["prompt"] != undefined) {
                    _this.Write(p["prompt"]);
                }
                var callback = new Pjs2.ReturnCallback();
                _this.ReadLine(function (s) {
                    if (!p["invisible"]) {
                        _this.WriteLine(s);
                    }
                    callback.Return(s);
                    return false;
                });
                return callback;
            }, [
                new Pjs2.FuncParameterDefinition("Prompt", false, true),
                new Pjs2.FuncParameterDefinition("Invisible", false, false, function (o) {
                    return typeof o == "boolean";
                })
            ], "Read-Host"));
        }
        Pjs2Console.prototype.KeyPress = function (ev) {
            if (!this.running) {
                if (ev.keyCode == 13 && ev.shiftKey) {
                    this.script += this.input.value + "\n";
                } else if (ev.keyCode == 13) {
                    this.script += this.input.value;
                    this.input.value = "";
                    this.CallReaders(this.script);
                    this.script = "";
                }
                _super.prototype.KeyPress.call(this, ev, false);
                return;
            }
            if (ev.keyCode == 38) {
                this.historyPos--;
                if (this.historyPos < 0)
                    this.historyPos = 0;
                if (this.history[this.historyPos])
                    this.input.value = this.history[this.historyPos];
            } else if (ev.keyCode == 40) {
                this.historyPos++;
                if (this.historyPos >= this.history.length)
                    this.historyPos = this.history.length - 1;
                if (this.history[this.historyPos])
                    this.input.value = this.history[this.historyPos];
            } else if (ev.keyCode == 13 && ev.shiftKey) {
                this.multiLine = true;
                this.ReadScriptLine();
                this.Write("...> ");
            } else if (ev.keyCode == 13 && !ev.shiftKey) {
                this.input.value = this.input.value.trim();
                var lch = this.input.value.charAt(this.input.value.length - 1);
                if (lch == "|" || lch == "{" || lch == "(") {
                    this.multiLine = true;
                }
                var end = !(this.multiLine && this.input.value != "");
                this.ReadScriptLine();
                if (end) {
                    this.ExecuteScript();
                } else {
                    this.Write("...> ");
                }
            }
            _super.prototype.KeyPress.call(this, ev, false);
            return true;
        };

        Pjs2Console.prototype.ReadScriptLine = function () {
            var val = this.input.value;
            this.input.value = "";
            this.script += val + "\n";
            this.WriteLine(val);
            this.history.push(val);
            this.historyPos = this.history.length;
        };

        Pjs2Console.prototype.ExecuteScript = function () {
            var _this = this;
            try  {
                var p = this.parser.ReadScript(this.script);
            } catch (e) {
                this.WriteError("Parsing error: " + e);
                this.script = "";
                return;
            }
            this.script = "";
            if (this.showParsedScript) {
                this.settings.foregroundColor = "lightBlue";
                this.Write("Parsed script: ");
                this.WriteLine(JSON.stringify(p));
                this.settings.foregroundColor = "white";
            }

            this.running = false;

            try  {
                var result = p.Run(this.runtime);
                Pjs2.Enumerable.forEach(result, function (o) {
                    if (o != null)
                        _this.WriteResult(o);
                }).OnError(function (e, f) {
                    _this.WriteError(e);
                    if (f) {
                        _this.running = true;
                        _this.Write("Pjs2> ");
                    }
                }).OnMessage(function (msg) {
                    _this.WriteLine(msg);
                }).OnReturn(function () {
                    _this.running = true;
                    _this.Write("Pjs2> ");
                });
            } catch (e) {
                this.running = true;
                this.WriteError("Runtime error: " + e);
                this.Write("Pjs2> ");
            }
        };

        Pjs2Console.prototype.WriteResult = function (data, actualTable) {
            if (typeof actualTable === "undefined") { actualTable = null; }
            var f = FormatingRules.FromObj(data);

            if (f.type == "table") {
                // TODO: tables
                this.WriteError("sorry table are not currently supported");
            } else if (f.type == "list") {
                this.WriteList(data, f);
            } else if (f.type == "json") {
                this.WriteJson(data, f);
            } else if (f.type == "toString") {
                this.WriteLine(data.toString());
            } else if (f.type == "custom") {
                f.customFormater(data, this);
            } else
                throw "not supported format";
        };

        Pjs2Console.prototype.WriteFormatedData = function (data, format) {
            var fn = format.type;
            if (fn != "list" && fn != "table" && fn != "json" && fn != "toString")
                throw "invalid format identifier";
            if (fn == "table") {
                return this.WriteTable(data, format.parameterNames);
            }
            if (fn == "toString")
                return this.WriteLine(data.toString());
        };

        Pjs2Console.prototype.WriteResultItem = function (data, format) {
            if (data instanceof Array)
                this.WriteFormatedData(data, format);
            else if (format.type == "json")
                this.WriteJson(data, format);
            else if (format.type == "list") {
                this.WriteList(data, format);
            }
        };

        Pjs2Console.prototype.WriteList = function (data, format) {
            var _this = this;
            if (typeof format === "undefined") { format = null; }
            var props = new Array();
            for (var p in data) {
                if (typeof data[p] != "function") {
                    props.push(p);
                }
            }
            var l = 0;
            props.forEach(function (v) {
                if (l < v.length)
                    l = v.length;
            });
            props.forEach(function (v) {
                _this.Write(v);
                _this.Write(Array(l + 2 - v.length).join(" "));
                _this.Write(": ");
                _this.WriteLine(Pjs2Console.ObjToString(data[v]));
            });
        };

        Pjs2Console.prototype.WriteTable = function (data, params, autoSize) {
            var _this = this;
            if (typeof autoSize === "undefined") { autoSize = true; }
            var t = new Array();
            var colWidth = new Array();
            for (var i = 0; i < params.length; i++) {
                colWidth[i] = params[i].length;
            }
            if (!autoSize) {
                var w = this.width;
                colWidth = Array(params.length).map(function (cw) {
                    return w / params.length;
                });
            }
            data.forEach(function (d) {
                var row = new Array();
                params.forEach(function (p, i) {
                    var cell = Pjs2Console.ObjToString(d[p]);
                    row.push(cell);
                    if (autoSize && colWidth[i] < cell.length)
                        colWidth[i] = cell.length;
                });
                t.push(row);
            });

            this.WriteTableRow(params, colWidth);
            this.WriteTableRow(params.map(function (p) {
                return Array(p.length + 1).join("-");
            }), colWidth);
            t.forEach(function (r) {
                _this.WriteTableRow(r, colWidth);
            });
            this.WriteLine("");
        };

        Pjs2Console.prototype.WriteTableRow = function (data, w) {
            var _this = this;
            data.forEach(function (d, i) {
                _this.Write(d);
                _this.Write(Array(w[i] - d.length + 2).join(" "));
            });
            this.WriteLine("");
        };

        Pjs2Console.prototype.WriteJson = function (data, format, spacing) {
            if (typeof format === "undefined") { format = null; }
            if (typeof spacing === "undefined") { spacing = "\t"; }
            if (!format || !format.params)
                this.WriteLine(JSON.stringify(data.value, null, spacing));
            else {
                var obj = {};
                for (var p in format.params) {
                    obj[p] = data.value[p];
                }
                this.WriteLine(JSON.stringify(obj, null, spacing));
            }
        };

        Pjs2Console.prototype.WriteError = function (msg) {
            var f = this.settings.backgroundColor;
            this.settings.backgroundColor = "red";
            this.WriteLine(msg);
            this.settings.backgroundColor = f;
        };

        Pjs2Console.ObjToString = function (data) {
            if (data == null)
                return "null";
            if (data == undefined)
                return "undefined";
            if (data instanceof Array)
                return "[" + data.length + "]";

            var t = data.$type || typeof data;
            if (t == "function")
                return "function (...) {...}";
            if (FormatingRules.FromObj(data).type == "toString")
                return data.toString();
            return t + "{...}";
        };
        return Pjs2Console;
    })(HtmlConsole);
    Pjs2.Pjs2Console = Pjs2Console;

    var FormatingRules = (function () {
        function FormatingRules(type, params) {
            if (typeof params === "undefined") { params = null; }
            this.type = type;
            this.params = params;
        }
        Object.defineProperty(FormatingRules.prototype, "parameterNames", {
            get: function () {
                var p = new Array();
                for (var i in this.params) {
                    p.push(i);
                }
                return p;
            },
            enumerable: true,
            configurable: true
        });

        FormatingRules.FromObj = function (obj) {
            if (typeof obj.$getFromattingRules === "function") {
                return obj.$getFromattingRules();
            }
            if (obj.$formattingRules != null) {
                return obj.$formattingRules;
            }
            if (obj.$type != null && FormatingRules.RulesForTypes[obj.$type]) {
                return FormatingRules.RulesForTypes[obj.$type](obj);
            }
            return this.RulesForTypes[typeof obj](obj);
        };

        FormatingRules.FromObjTable = function (obj) {
            return FormatingRules.Table(FormatingRules.IntersectParameters(obj));
        };

        FormatingRules.Table = function (p) {
            var params = {};
            p.forEach(function (v) {
                return params[v] = new FormatingRules("toString");
            });
            return new FormatingRules("table", params);
        };

        FormatingRules.IntersectParameters = function (obj) {
            var p = FormatingRules.FromObj(obj[0]).parameterNames;

            obj.forEach(function (v) {
                var lp = FormatingRules.FromObj(v).parameterNames;
                p = p.filter(function (i) {
                    return lp.some(function (lpi) {
                        return lpi == i;
                    });
                });
            });
            return p;
        };
        FormatingRules.RulesForTypes = {
            "number": function (obj) {
                return new FormatingRules("toString");
            },
            "string": function (o) {
                return new FormatingRules("toString");
            },
            "boolean": function (o) {
                return new FormatingRules("toString");
            },
            "function": function (o) {
                return new FormatingRules("toString");
            },
            "object": function (o) {
                return new FormatingRules("json");
            },
            "FunctionInfo": function (obj) {
                return new FormatingRules("table", { name: new FormatingRules("toString"), type: new FormatingRules("toString") });
            }
        };
        return FormatingRules;
    })();
    Pjs2.FormatingRules = FormatingRules;
})(Pjs2 || (Pjs2 = {}));
//# sourceMappingURL=pjs2-console.js.map
